repo: Add `query_file` API
authorColin Walters <walters@verbum.org>
Sat, 26 Feb 2022 13:46:50 +0000 (08:46 -0500)
committerColin Walters <walters@verbum.org>
Fri, 6 May 2022 16:53:57 +0000 (12:53 -0400)
The underlying `ostree_repo_load_file()` API has the caller pass
`NULL` for output arguments it doesn't want.  This isn't sanely
bindable in Rust - what the generator does is always request
all values, but maps them all to `Option<T>`.

The main cases are where a user wants either metadata, or both
metadata and content.  This API gives just metadata; it's a
bit more efficient as we don't need to open the file, and doesn't
require the caller to `unwrap()`.

rust-bindings/rust/src/repo.rs
rust-bindings/rust/tests/repo/mod.rs

index 147199c907f08e822e8024e203872e49ebf42ede..35a15248a98e1dbd01e217165d709a187afd45b3 100644 (file)
@@ -269,6 +269,37 @@ impl Repo {
         Ok(self.resolve_rev(refspec, false)?.unwrap())
     }
 
+    /// Query metadata for a content object.
+    ///
+    /// This is similar to [`load_file`], but is more efficient if reading the file content is not needed.
+    pub fn query_file<P: IsA<gio::Cancellable>>(
+        &self,
+        checksum: &str,
+        cancellable: Option<&P>,
+    ) -> Result<(gio::FileInfo, glib::Variant), glib::Error> {
+        unsafe {
+            let mut out_file_info = ptr::null_mut();
+            let mut out_xattrs = ptr::null_mut();
+            let mut error = ptr::null_mut();
+            let r = ffi::ostree_repo_load_file(
+                self.to_glib_none().0,
+                checksum.to_glib_none().0,
+                ptr::null_mut(),
+                &mut out_file_info,
+                &mut out_xattrs,
+                cancellable.map(|p| p.as_ref()).to_glib_none().0,
+                &mut error,
+            );
+            if error.is_null() {
+                debug_assert!(r != 0);
+                Ok((from_glib_full(out_file_info), from_glib_full(out_xattrs)))
+            } else {
+                debug_assert_eq!(r, 0);
+                Err(from_glib_full(error))
+            }
+        }
+    }
+
     /// Write a content object from provided input.
     pub fn write_content<P: IsA<gio::InputStream>, Q: IsA<gio::Cancellable>>(
         &self,
index 5d59aa5241373a1fe7824ccee87d329a3a81676d..703dc735866a4236aac0ca28725ed4423d694eab 100644 (file)
@@ -89,6 +89,15 @@ fn repo_traverse_and_read() {
         .unwrap();
     // Right now, the uid/gid are actually that of the test runner
     assert_eq!(dirmeta.mode, 0o40750);
+
+    let (finfo, _xattrs) = test_repo
+        .repo
+        .query_file(
+            "89f84ca9854a80e85b583e46a115ba4985254437027bad34f0b113219323d3f8",
+            NONE_CANCELLABLE,
+        )
+        .unwrap();
+    assert_eq!(finfo.size(), 5);
 }
 
 #[test]